/*********************************************************************************************************
 *  ------------------------------------------------------------------------------------------------------
 *  file description
 *  ------------------------------------------------------------------------------------------------------
 *         \file  queue.h
 *        \brief  This is a general-purpose C language queue module, with circular mode and common data structure
 *       \author  Lamdonn
 *        \email  Lamdonn@163.com
 *      \version  1.1.0
 *      \license  GPL2
 *    \copyright  Copyright (C) 2023 Lamdonn.
 ********************************************************************************************************/
#ifndef __queue_H
#define __queue_H

#include "deque.h"

/* queue type define */
typedef struct
{
    DEQUE parent;                       /* parent object */
} QUEUE, *queue_t;

/* queue orgin define */
#define QUEUE_ORGIN_FRONT               DEQUE_ORGIN_FRONT
#define QUEUE_ORGIN_BACK                DEQUE_ORGIN_BACK

/* control mode */
#define QUEUE_MODE_DEFAULT              DEQUE_MODE_DEFAULT      /* default mode */
#define QUEUE_MODE_READ                 DEQUE_MODE_READ         /* readable mode */
#define QUEUE_MODE_MODIFY               DEQUE_MODE_MODIFY       /* modifiable mode */
#define QUEUE_MODE_OVERWRITE            DEQUE_MODE_OVERWRITE    /* overwrite mode, when the queue is full, the new data overwrites the old data */
#define QUEUE_MODE_POP_RESET            DEQUE_MODE_POP_RESET    /* pop data and reset item */
#define QUEUE_MODE_POP_HOLD             DEQUE_MODE_POP_HOLD     /* pop data but not delete */
#define QUEUE_MODE_LMT_PUSH             DEQUE_MODE_LMT_PUSH     /* limit push */
#define QUEUE_MODE_LMT_POP              DEQUE_MODE_LMT_POP      /* limit pop */
#define QUEUE_MODE_RESIZE               DEQUE_MODE_RESIZE       /* resize */
#define QUEUE_MODE_DROP_FRONT           DEQUE_MODE_DROP_FRONT   /* when reducing the queue, the front is lost first */

/* set way */
#define QUEUE_SET_MODE                  DEQUE_SET_MODE
#define QUEUE_RESET_MODE                DEQUE_RESET_MODE

/** 
 *  \brief initialize queue
 *  \param[in] queue: queue handler
 *  \param[in] array: address of array
 *  \param[in] dsize: size of queue items
 *  \param[in] capacity: capacity of queue
 *  \return 1: success or 0: fail
 */
int queue_init(queue_t queue, void* array, int dsize, int capacity);

/** 
 *  \brief release queue
 *  \param[in] queue: queue handler
 *  \return none
 */
void queue_deinit(queue_t queue);

/** 
 *  \brief create queue
 *  \param[in] dsize: size of queue items
 *  \param[in] capacity: capacity of queue
 *  \return queue handler or NULL: fail
 */
queue_t queue_create(int dsize, int capacity);

/** 
 *  \brief delete queue created by queue_create function
 *  \param[in] queue: queue handler
 *  \return none
 */
void queue_delete(queue_t queue);

/** 
 *  \brief judge whether the queue is empty
 *  \param[in] queue: queue handler
 *  \return 1: empty or 0: not empty
 */
int queue_empty(queue_t queue);

/** 
 *  \brief check whether the queue is full
 *  \param[in] queue: queue handler
 *  \return 1: full or 0: not full
 */
int queue_full(queue_t queue);

/** 
 *  \brief get current items size
 *  \param[in] queue: queue handler
 *  \return size of item
 */
int queue_size(queue_t queue);

/** 
 *  \brief push data into queue
 *  \param[in] queue: queue handler
 *  \param[in] data: address of queue item data
 *  \return 1: success or 0: fail
 */
int queue_push(queue_t queue, void* data);

/** 
 *  \brief push data from queue
 *  \param[in] queue: queue handler
 *  \param[out] data: address of queue item data
 *  \return 1: success or 0: fail
 */
int queue_pop(queue_t queue, void* data);

/** queue_clear
 *  \brief clean queue
 *  \param[in] queue: queue handler
 *  \return none
 */
void queue_clear(queue_t queue);

/** 
 *  \brief get the pointer of queue's item
 *  \param[in] queue: queue handler
 *  \param[in] index: queue index
 *  \param[in] orgin: QUEUE_ORGIN_FRONT or QUEUE_ORGIN_BACK
 *  \return pointer of queue's item
 */
void* queue_data(queue_t queue, int index, int orgin);

/** 
 *  \brief insert data to queue
 *  \param[in] queue: queue handler
 *  \param[in] index: queue index
 *  \param[in] data: address of queue item data
 *  \param[in] orgin: QUEUE_ORGIN_FRONT or QUEUE_ORGIN_BACK
 *  \return 1: success or 0: fail
 */
int queue_insert(queue_t queue, int index, void* data, int orgin);

/** 
 *  \brief erase items from the queue
 *  \param[in] queue: queue handler
 *  \param[in] begin: begin index of queue
 *  \param[in] end: end index of queue
 *  \param[in] orgin: QUEUE_ORGIN_FRONT or QUEUE_ORGIN_BACK
 *  \return 1: success or 0: fail
 */
int queue_erase(queue_t queue, int begin, int end, int orgin);

/** 
 *  \brief read the data of queue
 *  \param[in] queue: queue handler
 *  \param[in] index: queue index
 *  \param[out] data: address of queue item data
 *  \param[in] orgin: QUEUE_ORGIN_FRONT or QUEUE_ORGIN_BACK
 *  \return 1: success or 0: fail
 */
int queue_read(queue_t queue, int index, void* data, int orgin);

/** 
 *  \brief modify the data of queue
 *  \param[in] queue: queue handler
 *  \param[in] index: queue index
 *  \param[in] data: address of queue item data
 *  \param[in] orgin: QUEUE_ORGIN_FRONT or QUEUE_ORGIN_BACK
 *  \return 1: success or 0: fail
 */
int queue_modify(queue_t queue, int index, void* data, int orgin);

/** 
 *  \brief get queue capacity
 *  \param[in] queue: queue handler
 *  \return the capacity of the queue
 */
int queue_capacity(queue_t queue);

/** 
 *  \brief resize the queue
 *  \param[in] queue: queue handler
 *  \param[in] capacity: new capacity of queue
 *  \return 1: success or 0: fail
 */
int queue_alter_capacity(queue_t queue, int capacity);

/** 
 *  \brief modify queue's mode
 *  \param[in] queue: queue handler
 *  \param[in] mode: queue mode
 *  \param[in] set: QUEUE_SET_MODE or QUEUE_RESET_MODE
 *  \return none
 */
void queue_mode(queue_t queue, int mode, int set);

/** 
 *  \brief macro definition method for creating queue
 *  \param[in] type: tpye of item(e.g int char)
 *  \param[in] capacity: capacity of queue
 *  \return queue handler
 */
#define queue(type, capacity)           (queue_create(sizeof(type),(capacity)))

/** 
 *  \brief define a const queue, end use does not need to be deleted
 *  \param[in] type: tpye of item(e.g int char)
 *  \param[in] capacity: capacity of queue
 *  \return const queue
 */
#define const_queue(type, capacity)     (queue_t)(&(DEQUE){{2,(type[capacity]){},sizeof(type),0},capacity,0,0,0})

/** 
 *  \brief macro definition method for delete queue
 *  \param[in] queue: queue handler
 *  \return none
 */
#define _queue(queue)                   do{queue_delete(queue);(queue)=NULL;}while(0)

/** 
 *  \brief macro definition method for get front item of queue
 *  \param[in] queue: queue handler
 *  \param[in] type: tpye of item
 *  \param[in] i: index
 *  \return reference to the specified item
 */
#define queue_at(queue, type, i)        (*(type *)queue_data((queue),(i),QUEUE_ORGIN_FRONT))

/** 
 *  \brief macro definition method for get front item of queue
 *  \param[in] queue: queue handler
 *  \param[in] type: tpye of item
 *  \param[in] i: index
 *  \return reference to the specified item
 */
#define queue_front(queue, type, i)     (*(type *)queue_data((queue),(i),QUEUE_ORGIN_FRONT))

/** 
 *  \brief macro definition method for get back item of queue
 *  \param[in] queue: queue handler
 *  \param[in] type: tpye of item
 *  \param[in] i: index
 *  \return reference to the specified item
 */
#define queue_back(queue, type, i)      (*(type *)queue_data((queue),(i),QUEUE_ORGIN_BACK))

#endif
